【问题标题】:angular does not find an uploaded image角度找不到上传的图像
【发布时间】:2019-03-06 01:12:15
【问题描述】:

场景很简单。使用表单上传图片,如果上传成功,刷新相册。我使用 angular6 和 ng-carousel。所有系统都在我的 Windows 10 笔记本电脑中本地设置。

表单被上传,文本数据保存在数据库中,图像保存在节点 8.11.1 的文件中。我将图像保存在src/assets/images 中。我可以看到更改,并且在上传时没有错误。

但是,上传后,我尝试使用新图像的 URL 将其添加为轮播中的最后一张图像,但我得到的只是 404 错误。该 URL 类似于 http://localhost:4200/assets/images/unsplash.jpg 该 URL 有效,图像在那里并且所有其他轮播图像使用相同的 URL。但是,新图像有 404 错误。我必须重新编译角度应用程序才能看到图像。不只是刷新页面,重新编译整个应用程序。

我不知道如何解决这个问题。我尝试在前端使用 File 对象或 HTML5 FileReader API,而不依赖于在图像上传后创建 URL。但是他们没有 URL 并且 ng-carousel 需要像 /assets/images/img.jpg 这样的 URL 才能工作。为了使用某种 URL,我也尝试从节点获取临时 URL 并将其返回给前端,但由于它是 temp 文件夹 URL,浏览器不会让我使用它。我也尝试使用createObjectURL,但并非所有浏览器都支持。我还尝试在保存图像后执行GET 并从数据库中获取所有图像名称,再次循环它们并再次提供轮播模板。没有。仍然是404错误。我必须重新编译应用程序。

发生了什么?这是一个角度6的问题吗?安全限制?请帮我解决这个问题,我不知道如何处理了。

代码大纲。

形式

<form *ngIf="pointPartsActive" [formGroup]="imageUpload" (ngSubmit)="imageUploadSubmitted($event.target)" >
  <input type="file"  (change)='imageChange($event)' #imageInput id="imageInput" name = 'imageInput'  accept=".png, .jpg, .jpeg, .gif" formControlName="imageInput" > 
  <input type="text" formControlName="imageName" name='imageName' placeholder="name" >
  <button type="submit" >Submit</button>  
</form>

html轮播模板,添加自定义html也可以当场删除图片。

<ngb-carousel #carousel *ngIf="images" (slide)="onSlide($event)"> 
  <ng-template ngbSlide *ngFor="let im of images; let i = index"  id="{{im.id}}">
    <img src='../assets/images/{{im.name}}' >
    <div class='carousel-img-details'>
        <button type="button" (click)='deletepic(im.photoId)'>delete</button>   
    </div>
  </ng-template>
</ngb-carousel>

表单提交

  imageUploadSubmitted(form){  
    let formData = new FormData(form);
    let eb =null;
    this.http.post('http://localhost:3000/cms/upload',formData,{reportProgress:true,observe:'events'}).subscribe(
      event=>{        
        if(event.type === HttpEventType.Response){     
          eb = event.body;              
          if(eb.success){                  
            this.imageUpload.reset();                                                 
            this.addpic(eb.data);            
          }
        }        
    }); 
  }

成功提交表单后,更新为轮播提供数据的数组。它是一个简单的 json 对象数组,例如 [{'id':1,'name':'James'},{'id':2,'name':'Nolan'}],并通过 ngFor 提供轮播。

  addpic(data){
    let slide = null;    
    this.images.push({
        'photoId':Number(data.id)
        'id': this.images.length,   
        'name': data.name    
    });     
     //get the id of the last slide and go there :          
     setTimeout(() => {
      slide = this.images[this.images.length-1].id;    
      this.carousel.select(slide); 
     });
     this.images = this.images.slice(); //try to "refresh" array itself
  }

stackblitz中的代码逻辑

谢谢

【问题讨论】:

  • 澄清:您是否将图像上传到资产文件夹?当您在本地运行应用程序时,您是使用 ng serve 运行它,还是在 ng build 之后从节点服务器运行它。有两个 assets 文件夹,一个在 src 中,一个在 dist 中,如果您使用 build 运行应用程序,则图像必须在 dist 文件夹中。
  • @Engam 是的。网址是http://localhost:4200/assets/images/1537906640981-unsplash.jpg
  • @Engam 一个 CMD 为节点 8.11.1 运行 nodemon,另一个为 angular6 运行 ng serve。我将图像保存在 src/assets/images 中。我有提到我是新手吗?哦,上帝,这是一些愚蠢的细节,我只是浪费了所有这些时间,也浪费了大家的时间,对吧?
  • 在选择图像后的 stackblitz 中,我看到此错误:ERROR TypeError: Cannot read property 'nativeElement' of undefined at FileReader.reader.onload (app.component.ts:52)
  • @Kalamarico 我失去了你。在什么功能上?我看到 52 checkfiles 和 readfiles 之间有一个空行。

标签: angular image url file-upload angular6


【解决方案1】:

Angular 使用 AOT(Ahead of Time) 编译,它将读取编译时可用的现有文件。上传的图片要保存在服务器端代码中,例如:文件夹server/uploads

当调用图像链接的API时,响应可以有baseURL/file-name。对于您的开发服务器,它将是localhost:3000/uploads/unsplash.jpg。确保您已将上传文件夹设为静态。

如果您在服务器端使用节点 JS (Express),这里有一个示例

const fs = require('fs-extra')
app.use(express.static(__dirname + '/uploads'));

app.get('/gallery',(req, res) => {
    fs.readdir(('./uploads'),(err,files) => {
            let filePath = []
            files.forEach(filename => {
                filePath.push('http://localhost:3000/uploads/' + filename)
            })
            res.json({
                files: filePath
            })
    })
})

app.listen(3000, () => {
    console.log('Server started on port:', 3000)
})

这将为您提供uploads文件夹中图像的路径,并且可以在客户端查看,而不是将其存储在资产文件夹中

【讨论】:

    【解决方案2】:

    这可能是您的解决方案:

    对于实时应用程序,您可能希望将图像保存在文件服务器上(例如 Amazon AWS 上的 AWS S3),并将指向该文件的链接存储在数据库中。

    对于您的 localhost 项目,您可以使用 http-server 作为此文件服务器,或者您可以将 express framework 与您的节点应用程序一起使用。

    npm install http-server -g
    http-server C:/link/to/a/folder/you/have/saved/the/images/in
    

    然后您必须将链接保存到您的文件中,无论是在 db(数据库)中还是在文本文件中。为此,我建议您设置一个本地 MongoDB database。您可能需要一些时间才能进入,但这是很好的学习经历。您可以使用https://mongoosejs.com/ 与您的节点应用程序进行通信。

    然后,当您上传新图像时,将其从前端 Angular 应用程序发送到后端节点/express 应用程序,将文件保存在文件夹中并将链接保存在数据库中。使用 https-server,您将能够立即访问图像(可能会有一些延迟)。通过存储在 db 中的链接,您可以在刷新应用程序时通过 http get 请求将 db 中的数据发送到前端。

    我希望这会帮助你实现你的目标:)

    【讨论】:

    • 我有 node+express/angular/postgres 。我将图像名称保存在数据库中,并尝试在轮播中以角度重新创建 URL,如您在模板中看到的 &lt;img src='../assets/images/{{im.name}}' &gt;。我有你的建议。现在唯一的问题是 404/assets 文件夹的东西。将所有内容都放入资产中是有意义的,因为它们最终会放在那里。所以,除非 dist 中的资产可以自动返回一个新上传图片的有效 URL,否则我会被炸吗? Angular 只是让我悬而未决,选项是亚马逊和更多包?对于一个简单的图像 URL??伟大的工作 Angular!
    • 我想我必须构建应用程序并测试 dist 的响应方式。否则我会测试http-server。我该如何选择使用快递?再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2017-10-15
    • 2022-06-26
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 2021-07-05
    • 2019-01-10
    • 1970-01-01
    相关资源
    最近更新 更多