首頁  >  問答  >  主體

java - ServletOutputStream 和图片的关系

在前台页面有如下语句
<img onclick="this.src='/ran/random?random='+Math.random()" alt="验证码,点击图片更换" src="/ran/random?random=0.2868249340216069" width="86" height="40">

其中src 指向的地址不是一个img文件,而是一个转到SpringMVC的类中方法
src="/ran/random?random=0.2868249340216069"

方法如下:

@Controller
public class RandomCodeController {
    @RequestMapping(value={"/ran/random"})
    public void genericRandomCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
    response.setHeader("Cache-Control", "private,no-cache,no-store");
    response.setContentType("image/png");
    HttpSession session = request.getSession();
    int width = 85;
    int height = 28;
    BufferedImage image = new BufferedImage(width, height, 2);
    Graphics2D g = image.createGraphics();
    g.setComposite(AlphaComposite.getInstance(3, 1.0f));
    Random random = new Random();
    g.setColor(new Color(231, 231, 231));
    g.fillRect(0, 0, width, height);
    g.setFont(new Font("Microsoft YaHei", 2, 24));
    String sRand = "";
    for (int responseOutputStream = 0; responseOutputStream < 4; ++responseOutputStream) {
        String rand = String.valueOf(random.nextInt(10));
        sRand = sRand + rand;
        g.setColor(new Color(121, 143, 96));
        g.drawString(rand, 13 * responseOutputStream + 16, 23);
    }
    session.setAttribute("COMMON_RAND_CODE", (Object)sRand);
    g.dispose();
    ServletOutputStream var12 = response.getOutputStream();
    ImageIO.write((RenderedImage)image, "png", (OutputStream)var12);
    var12.close();
    }
}

所以其实这个src相联系的是一个ServletOutputStream
这个地方我不太理解
ServletOutputStream如何和一个图片联系起来?

ringa_leeringa_lee2765 天前849

全部回覆(3)我來回復

  • PHP中文网

    PHP中文网2017-04-18 10:35:36

    不只是圖片,其他文件也是以流的形式傳輸的。瀏覽器把後台給的串流解析成了圖片了。

    回覆
    0
  • 高洛峰

    高洛峰2017-04-18 10:35:36

    說穿了,圖片是怎麼展示到你的電腦上的呢,就是一個透過網路資料流。
    所謂指向具體圖片,或者是其他伺服器上的資源也一樣,就是你的web伺服器將對應的檔案以流的形式讀取,然後透過網路發出去。瀏覽器端接到的都是流,他只能根據mime type去判斷這個流內的文件是什麼
    以偽代碼簡單來說就是這樣的

    socket =  ss.accept();
    fileInput = new FileInput(socket.getURI());
    for(xxxx){  // 将输入的内容发送到输出流中
        ....
    }

    而你上面那段程式碼 其實主要是產生了一個圖片,只不過他沒有將文件寫道硬碟,而是直接發送給了瀏覽器端。
    ImageIO.write(image, "png", output) 这句实际上就是将image物件的資料寫入到對應的位置,如果這個流是一個fileoutput,那他就會寫入到硬碟,所以你也可以改成這樣。

    ImageIO.write(image, "png", new FileOutputStream(serverPath + "/images/xxx.png"));
    response.redirect("/images/xxx.png");
    //定时计划 删除资源
    task.delFile(serverPath  + "/images/xxx.png")

    回覆
    0
  • 怪我咯

    怪我咯2017-04-18 10:35:36

    這是檔案流在Servlet中傳輸方式問題,ServletOutputStream透過HttpServletResponse.getOutputStream()與瀏覽器用戶端實作連通,ImageIO.write()將檔案轉換為輸出流,而至於中間的連通過程及具體實作方式,那就需要你去看原始碼了。

    估計你也不想研究這麼深,知道檔案流在B/S結構中傳輸大致流程,了解具體程式碼實作方式和參數設定規則即可。另外,建議你把驗證碼生成程式碼提取出來單獨寫一個方法,然後再讓RandomCodeController()方法調用,這樣結構簡單明了

    回覆
    0
  • 取消回覆