Skip to content

fix(import): replace external image URL with local path after download#3140

Open
bigsearcher wants to merge 1 commit into
nextcloud:masterfrom
bigsearcher:localize-image-on-import
Open

fix(import): replace external image URL with local path after download#3140
bigsearcher wants to merge 1 commit into
nextcloud:masterfrom
bigsearcher:localize-image-on-import

Conversation

@bigsearcher
Copy link
Copy Markdown

Summary

When a recipe is imported from a URL, RecipeService::addRecipe() downloads the image and writes it to the recipe folder as full.jpg (via ImageService::setImageData()), but recipe.json keeps the original external URL in its image field. This patch rewrites that field to the user-relative path of the local file after the download succeeds, so:

  • The source URL no longer leaks back to the user on edit (visible in the Image field of the editor).
  • recipe.json self-consistently reflects what is actually on disk.
  • Future re-saves don't risk a re-download from the original host if the field is touched.

Background

The frontend (RecipeCard.vue, RecipeImages.vue) renders images via recipe.imageUrl, which the backend (RecipeImplementation.php) generates as a link to the cookbook.recipe.image route — i.e. the local file. So end-user browsing already does not hit the external host. This patch only fixes the persistent state of the JSON field.

I have ~30k imported recipes; on roughly half of them, recipe.json#image was still an external URL pointing to all sorts of food blogs. Cleaning them up after the fact was a one-shot script, but new imports keep reintroducing the divergence — hence this fix at the source.

Test plan

  • Import a recipe from a URL with an image (e.g. any recipe blog with a JSON-LD image field). Confirm full.jpg exists in the recipe folder.
  • Open the imported recipe in edit mode. Confirm the Image field shows a path like /Recipes/<Recipe Name>/full.jpg, not the original URL.
  • Re-save the recipe without changes. Confirm no re-download happens (no outbound HTTP, image unchanged on disk).
  • Change the image to a different URL in edit mode. Confirm the new URL is fetched and the field is again rewritten to a local path on save.
  • Existing recipes with an unchanged URL in image are untouched (the new code runs only when image data is freshly fetched).

When importing a recipe from a URL, the image is fetched and saved
locally as full.jpg, but the 'image' field in recipe.json kept the
original URL. Two consequences:

1. The source URL leaks back to the user on edit (visible in the
   image field), even though the frontend serves the local copy via
   the cookbook.recipe.image API route.
2. Re-saving the recipe without changing the image still satisfies
   the change check on line 283 only because the strings match — but
   if anything mutates the field (e.g. a filter or user edit that
   does not intend to re-fetch), the importer would re-download from
   the external host on every save.

After setImageData() succeeds, rewrite the field to the user-relative
path of the local file (/<recipe_folder>/full.jpg) and re-write
recipe.json. The path is resolvable by the existing local-path branch
on line 297 should it ever be needed.
@github-actions
Copy link
Copy Markdown
Contributor

Test Results

    9 files    444 suites   1m 36s ⏱️
  589 tests   588 ✅ 1 💤 0 ❌
1 767 runs  1 763 ✅ 4 💤 0 ❌

Results for commit 06d9e6a.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant